package com.xbell.app.sys.controller;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.xbell.app.sys.common.ResponseMessage;

/**
 * Sentinel 控制器
 */
@RestController
@RequestMapping(value="sentinel")
public class SentinelController implements InitializingBean,EnvironmentAware {
	
	//@Value("${abc.test}")
	String abc;
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
	/// 手动控制
	//@SentinelResource(value="t1",blockHandler = "t1")
	@GetMapping("/flowm1")
	public ResponseMessage<Object> flowm1(String say){
		String key = "m1";
		Entry entry = null;
		try {
		  entry = SphU.entry(key);
		  // Write your biz code here.
		  // <<BIZ CODE>>
		} catch (Throwable t) {
			this.logger.info("进入拦截了");
		  if (!BlockException.isBlockException(t)) {
		    Tracer.trace(t);
		  }
		} finally {
		  if (entry != null) {
		    entry.exit();
		  }
		}
		return ResponseMessage.ok();
	}
	
	@SentinelResource(value="a1",blockHandler = "a1",entryType=EntryType.IN)
	@GetMapping(value="flowa1")
	public ResponseMessage<Object> flowa1(String say){
		return ResponseMessage.ok();
	}
	
	public ResponseMessage<Object> a1(String say,BlockException be){
		this.logger.error("降级了");
		return ResponseMessage.error("发生错误来了");
	}
	
	/**
	 * 熔断降级 - 慢调用
	 * @author 王文胜
	 * @date 2024年10月5日 下午4:01:07
	 * @param say
	 * @return
	 */
	@GetMapping("/degrade1")
	public ResponseMessage<Object> degrade1(String say){
		String key = "degrade1";
		Entry entry = null;
		try {
		  entry = SphU.entry(key);
		  // Write your biz code here.
		  // <<BIZ CODE>>
		  Thread.sleep((long) (Math.random()*1000));
		} catch (Throwable t) {
			this.logger.error("降级了"+t.getClass());
		  if (!BlockException.isBlockException(t)) {
		    Tracer.trace(t);
		  }
		} finally {
		  if (entry != null) {
		    entry.exit();
		  }
		}
		return ResponseMessage.ok();
	}
	public void initRule(String key) {
		if("m1".equals(key)||"a1".equals(key))
		{
			List<FlowRule> rules = new ArrayList<FlowRule>();
			FlowRule rule = new FlowRule(key); /// 资源
			rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // qps
			rule.setCount(2);
			rule.setLimitApp("default");
			rules.add(rule);
			FlowRuleManager.loadRules(rules);
		}
		else if("degrade1".equals(key)) {
			List<DegradeRule> rules = new ArrayList<DegradeRule>();
			DegradeRule rule = new DegradeRule(key); /// 资源
			rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // qps
			rule.setCount(200); // 请求响应时间
			rule.setTimeWindow(5); /// 熔断时长
			rule.setMinRequestAmount(5); /// 统计周期内的最小请求次数
			rule.setLimitApp("default");
			rule.setSlowRatioThreshold(0.3); /// 慢响应比例
			rules.add(rule);
			DegradeRuleManager.loadRules(rules);
		}
		
	}
	
	public void initRule() {
		List<FlowRule> rules = new ArrayList<FlowRule>();
		FlowRule rule = new FlowRule("hello");
		rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
		rule.setCount(2); // qps = 2
		rule.setLimitApp("default");
		rules.add(rule);
		FlowRuleManager.loadRules(rules);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		
		this.logger.error("初始化"+abc);
		this.initRule("m1");
		this.initRule("a1");
		this.initRule("degrade1");
	}

	@Override
	public void setEnvironment(Environment environment) {
		this.logger.error("setEnvironment"+environment.getProperty("abc.test"));
	}
}
